package com.example.rpc_core.servers;
import cn.hutool.core.util.IdUtil;
import com.example.rpc_core.RpcApplication;
import com.example.rpc_core.constance.ProtocolConstant;
import com.example.rpc_core.model.RpcRequestExample;
import com.example.rpc_core.model.RpcResponseExample;
import com.example.rpc_core.model.ServiceInfo;
import com.example.rpc_core.protocal.ProtocolMessage;
import com.example.rpc_core.protocal.ProtocolMessageDecoder;
import com.example.rpc_core.protocal.ProtocolMessageEnder;
import com.example.rpc_core.protocal.ProtocolMessageSerializableEnum;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetServer;
import io.vertx.core.net.NetSocket;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class TcpClient {
    public static RpcResponseExample doRequest(RpcRequestExample requestExample, ServiceInfo serviceInfo) throws ExecutionException, InterruptedException {

        Vertx vertx=Vertx.vertx();
        NetClient netClient = vertx.createNetClient();
        CompletableFuture<RpcResponseExample> objectCompletableFuture = new CompletableFuture<>();
        netClient.connect(serviceInfo.getServicePort(),serviceInfo.getServiceHost(),result->{
            if(!result.succeeded()){
                System.out.println("连接失败");
                return;
            }
            NetSocket socket = result.result();
            ProtocolMessage<RpcRequestExample> protocolMessage=new ProtocolMessage<>();
            ProtocolMessage.Header header=new ProtocolMessage.Header();
            header.setMagic(ProtocolConstant.PROTOCOL_MAGIC);
            header.setVersion(ProtocolConstant.PROTOCOL_VERSION);
            header.setSerializable((byte) ProtocolMessageSerializableEnum.getEnumByValue(
                    RpcApplication.getRpcConfig().getSerializable()).getKey());
            //生成全区请求id
            header.setRequestId(IdUtil.getSnowflakeNextId());
            protocolMessage.setHeader(header);
            protocolMessage.setBody(requestExample);
            //编码请求
            try {
                Buffer encode = ProtocolMessageEnder.encode(protocolMessage);
                socket.write(encode);

            } catch (IOException e) {
                throw new RuntimeException("协议信息编码失败");
            }
            TcpBufferHandlerWrapper tcpBufferHandlerWrapper=new TcpBufferHandlerWrapper(
                    buffer -> {
                        try {
                            ProtocolMessage<RpcResponseExample> decode =
                                    (ProtocolMessage<RpcResponseExample>) ProtocolMessageDecoder.decode(buffer);
                            objectCompletableFuture.complete(decode.getBody());

                        } catch (IOException e) {
                            throw new RuntimeException("消息协议解码失败");
                        }
                    }
            );
            socket.handler(tcpBufferHandlerWrapper);


        });
        RpcResponseExample rpcResponseExample = objectCompletableFuture.get();
        netClient.close();
        return rpcResponseExample;
    }

}
